use super::*;

/// Represents a JavaScript Symbol object
#[derive(Clone, Copy)]
pub struct Symbol<'val> {
	env: &'val Env,
	inner: sys::napi_value,
}

impl<'val> Symbol<'val> {
	/// Creates a new Symbol with an optional description
	pub fn new<'env>(env: &'env Env, description: &str) -> Result<'static, Symbol<'env>> {
		let mut ret = core::ptr::null_mut();
		unsafe { sys::napi_create_symbol(env.raw(), description.into_napi(env)?.raw(), &mut ret) }.result("napi_create_symbol")?;
		Ok(Symbol { env, inner: ret })
	}
}

impl<'val> FromNapi<'val> for Symbol<'val> {
	/// Converts from Value to Symbol
	fn from_napi(v: Value<'val>) -> Result<'static, Self> {
		if !v.is_symbol()? {
			return Err(Status::invalid_arg("symbol expected").into());
		}
		Ok(Symbol {
			env: v.env,
			inner: v.inner,
		})
	}
}

impl<'val> IntoNapi for Symbol<'val> {
	/// Converts from Symbol to Value
	fn into_napi<'env>(self, env: &'env Env) -> Result<'static, Value<'env>> {
		if self.env.raw() != env.raw() {
			return Err(Status::invalid_arg("self.env not eq arg env"));
		}
		Ok(Value::new(env, self.inner))
	}
}